/* 
 * File:   RemoteSource.cpp
 */
#include <fstream>
#include <vmime/vmime.hpp>
#include <vector>
#include <vmime/platforms/posix/posixHandler.hpp>
#include "iostream"
#include "ostream"
#include <stdlib.h>
#include <string>

#include "RemoteSource.h"
#include "RemoteAdress.h"
#include "MyCert.h"
#include "File.h"
#include "ActionsWithFiles.h"
#include "MyDate.h"
#include "Log.h"



void RemoteSource::rConnect()
{
   // Log::getInstance()->sDebugging(receive_adress.getComplexString());

    rsession =  vmime::create<vmime::net::session>();
    rsession -> getProperties().setProperty("store.imaps.server.port",receive_adress.port);
    vmime::utility::url url(receive_adress.getComplexString());
    rstore = rsession->getStore(url);
    rstore->setCertificateVerifier(vmime::create<myCertVerifier>());   
    rstore->connect();

}
void RemoteSource::sConnect()
{
    Log::getInstance()->sDebugging("RemoteSource::sConnect send_adress.mailbox "+send_adress.mailbox);
    ssession = vmime::create<vmime::net::session>();
    if ( send_adress.auth )
      ssession ->getProperties().setProperty("transport.smtp.options.need-authentication",true);
    if ( send_adress.tls )
       ssession ->getProperties().setProperty("transport.smtp.connection.tls",true);
       Log::getInstance()->sDebugging("\tURL "+send_adress.getComplexString());
       vmime::utility::url url(send_adress.getComplexString());
    trans = ssession->getTransport(url);
    trans->setCertificateVerifier(vmime::create<myCertVerifier>());
    trans->connect();
    
    if (trans->isConnected())
        Log::getInstance()->sDebugging("\tConnected for sending emails");
    else
        Log::getInstance()->sDebugging("\tCant connect to send messages");

}
bool RemoteSource::rConnected()
{
    if ( rstore->isConnected() ) return true;
        return false;
}

bool RemoteSource::sConnected()
{
    if (trans->isConnected() ) return true;
        return false;
}
std::vector<File>& RemoteSource::getRemoteFiles()
{


Log::getInstance ()->sDebugging ("getRemoteFiles");
    files.clear();
    folder = rstore->getDefaultFolder();
    folder->open(vmime::net::folder::MODE_READ_WRITE);

    std::vector<vmime::ref<vmime::net::message> > messages = folder->getMessages();

    folder->fetchMessages(messages,vmime::net::folder::FETCH_ENVELOPE);

    for (int i = 0; i < messages.size(); ++i)
    {
        vmime::ref<vmime::net::message> msg = messages[i];
        vmime::ref< const vmime::header> head = msg->getHeader();

        File buf;
        buf.message = msg;
        buf.number_in_folder = i + 1;

        string s;
        s = head->Subject()->generate();
        s.erase(0,9);
    

       if (s.length() >= sex.length())
       {
         string sbuf = s;
         sbuf.erase(sex.length(),sbuf.length()-sex.length());
         if (sex == sbuf)
         {


         s.erase(0,sex.length());
      //   cout << endl << endl << s << endl;
         string::iterator iter = s.begin ();
         while (*iter != ' ')
           {
             buf.name.push_back (*iter);
             iter++;
           }
         iter++;

         if (receive_adress.if_adv_adr)
           {
             Log::getInstance ()->sDebugging ("adv rem adr is "+receive_adress.adv_adr);
           }
         else
           Log::getInstance ()->sDebugging ("There is no adr rem adr");
          if ((receive_adress.if_adv_adr) && (receive_adress.adv_adr != buf.name))
                  continue;
        
         sbuf = "";

         while (*iter != ' ')
           {
             sbuf.push_back (*iter);
             iter++;
           }
         iter++;
         buf.date.setDate(sbuf);

        // cout << buf.name << endl;
       //  cout << sbuf << endl;

         s.erase(s.begin (), iter);

         // cout << endl << endl << s << endl << endl;
         if (s == "archive")
           {
            buf.if_archive = true;
            buf.if_synch = false;
           }

         if (s == "simple")
           {
           buf.if_archive = false;
           buf.if_synch = false;
           }
         if (s == "synch")
           {
             buf.if_synch = true;
             buf.if_archive = true;
           };

           buf.if_remote = true;
            files.push_back(buf);
         }
       }
    }

    return files;
}

void RemoteSource::setFileActions(std::vector<File>& files_)
{
        Log::getInstance ()->sDebugging ("setFileActions");
        for (int i = 0; i != files_.size(); ++i)
        {

            switch (files_[i].action)
         {
             case RECEIVE:
                 receiveFile(files_[i]);
                 break;
             case REMOVE:  
                 deleteFile(files_[i]);
                 break;
             case SEND:
                 sendFile(files_[i]);
                 break;
             default:
               //throw "RemoteSource::setFilesActions can't recognize action with File";
                 break;
         }
        }
 };
 void RemoteSource::preCleaning (std::vector<File>& files_)
 {
   Log::getInstance ()->sDebugging ("preCleaning");
     for (int i = 0; i != files_.size(); ++i)
        {

         File& file = files_.at(i);
         if (file.action == REMOVE )
                 deleteFile(file);
         }
   
 };


void RemoteSource::receiveFile(File& file_)
{

    {
     Log::getInstance ()->sDebugging ("\treceiveFile");
     vmime::ref<vmime::net::message>  msg = file_.message;
     ofstream myout;
     Log::getInstance ()->sDebugging ("\tfull local path "+file_.full_local_path);

     const char* tr = file_.full_local_path.c_str();
     myout.open(tr,ios::out);
     vmime::utility::outputStreamAdapter out(myout);
     vmime::ref<vmime::message> msgl = msg->getParsedMessage();
     vmime::utility::ref<vmime::message const> msgc = msgl; 
     const std::vector<vmime::utility::ref<vmime::attachment const> > atts = vmime::attachmentHelper::findAttachmentsInMessage(msgc,0);
     atts[0]->getData()->extract(out);

     Log::getInstance ()->sDebugging ("\t have extracted "+file_.full_local_path);
    }

 };
    
void RemoteSource::deleteFile(File& remote_file_)
{

    Log::getInstance()->sDebugging("RemoteSource::deleteFile "+remote_file_.name);
        folder->deleteMessage(remote_file_.number_in_folder);
};

RemoteSource::RemoteSource (RemoteAdress& receive_adress_, RemoteAdress& send_adress_): receive_adress(receive_adress_),send_adress(send_adress_)
    {
//      Log::getInstance()->sDebugging("in remotesource construct");
        sex = "NOT A MESSAGE, ONLY FOR EMAILSYNCH PROGRAMM USE: ";

    };
    
    
    void RemoteSource::sendFile(File& file_)
    {
     Log::getInstance()->sDebugging("RemoteSource::sendFile");
     vmime::messageBuilder mb;

     string metadata;
     if ( file_.if_archive )
       metadata = "archive";
     else
       metadata = "simple";
     if (file_.if_synch )
       metadata = "synch";

     string head = sex+file_.name+" "+file_.date.getstring()+" "+metadata ;
     if (file_.if_synch)
       head = sex+file_.synch_name+" "+file_.date.getstring()+" "+metadata ;

     Log::getInstance()->sDebugging("\tSubject is "+head);
     mb.setSubject(vmime::text(head));
     

     if ( send_adress.mailbox.size () == 0 )
       send_adress.mailbox = receive_adress.mailbox;
      if ( send_adress.mailbox.size () == 0 )
       send_adress.mailbox = send_adress.username;

     Log::getInstance()->sDebugging("\tExpeditor "+send_adress.mailbox);

     mb.setExpeditor(vmime::mailbox(send_adress.mailbox));

     if ( receive_adress.mailbox.size () == 0 )
       receive_adress.mailbox = receive_adress.username;

     Log::getInstance()->sDebugging("\tRecipient "+receive_adress.mailbox);

     mb.getRecipients().appendAddress(vmime::create<vmime::mailbox>(receive_adress.mailbox));

     Log::getInstance()->sDebugging("\tfull local path of file to be transport "+file_.full_local_path);

     vmime::ref<vmime::fileAttachment> att = vmime::create<vmime::fileAttachment>
     (
           file_.full_local_path,
           vmime::mediaType()
      );

     att->getFileInfo().setFilename(file_.name);
     mb.appendAttachment(att);
     vmime::ref<vmime::message> mdg = mb.construct();
     trans ->send(mdg);
    };

 
   


    



